<template>
  <basic-container>
    <el-card class="card">
      <el-row>
        <el-col :xs="24" :sm="6">
          <div class="head-info">
            <span>总任务</span>
            <p>{{ job.total }}</p>
          </div>
        </el-col>
        <el-col :xs="24" :sm="6">
          <div class="head-info">
            <span>等待中任务</span>
            <p>{{ job.pending }}</p>
          </div>
        </el-col>
        <el-col :xs="24" :sm="6">
          <div class="head-info">
            <span>运行中任务</span>
            <p>{{ job.running }}</p>
          </div>
        </el-col>
        <el-col :xs="24" :sm="6">
          <div class="head-info">
            <span>失败任务</span>
            <p class="red">
              {{ job.failed }}
            </p>
          </div>
        </el-col>
      </el-row>
    </el-card>
    <avue-crud
      ref="crud"
      v-model="form"
      :option="option"
      :table-loading="loading"
      :data="data"
      :page="page"
      :before-open="beforeOpen"
      :cell-style="cellStyle"
      :row-style="rowStyle"
      @row-update="rowUpdate"
      @row-save="rowSave"
      @row-del="rowDel"
      @row-click="rowClick"
      @refresh-change="refresh"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @on-load="onLoad"
    >
      <template slot="menu" slot-scope="{row}">
        <el-button type="text" icon="el-icon-video-play" size="medium" @click.stop="jobStatusHandler(row)">
          {{ jobStatusText(row) }}
        </el-button>
      </template>
    </avue-crud>
  </basic-container>
</template>

<script>
import { mapGetters } from 'vuex'

const listImplementJobsAction = 'monitor/job/listImplementJobs'
const pageJobTasksAction = 'monitor/job/pageJobTasks'
const addJobAction = 'monitor/job/addJob'
const updateJobAction = 'monitor/job/updateJob'
const startJobAction = 'monitor/job/startJob'
const stopJobAction = 'monitor/job/stopJob'
const pauseJobAction = 'monitor/job/pauseJob'
// const resumeJobAction = 'monitor/job/resumeJob'
const deleteJobAction = 'monitor/job/deleteJob'

export default {
  name: 'Job',
  data () {
    const statusDic = [
      {
        label: '是',
        value: true
      },
      {
        label: '否',
        value: false
      }
    ]
    return {
      job: {
        total: 0,
        pending: 0,
        running: 0,
        failed: 0
      },
      form: {},
      query: {
        operationType: 1
      },
      loading: true,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      selectionList: [],
      option: {
        // title: '日志表',
        border: true,
        menu: true,
        lazy: true,
        tip: true,
        tipPlacement: 'top-start',
        index: false,
        indexLabel: '序号',
        indexFixed: true,
        selection: true,
        selectionWidth: 60,
        selectionFixed: false,
        searchShow: true,
        addBtn: true,
        editBtn: true,
        viewBtn: true,
        excelBtn: false,
        printBtn: false,
        dialogDrag: true,
        dialogDirection: 'rtl',
        dialogType: 'dialog',
        searchMenuSpan: 10,
        selectClearBtn: false,
        column: [
          {
            label: '任务名称',
            prop: 'jobName',
            type: 'text',
            showWordLimit: true,
            maxlength: 200,
            rules: [
              {
                required: true,
                message: '任务名称不能为空',
                trigger: 'blur'
              }
            ],
            search: true,
            searchTip: '输入定时任务的名称',
            searchLabelWidth: 100,
            searchSpan: 8,
            searchRules: [{
              required: true,
              message: '请输入任务名称',
              trigger: 'blur'
            }]
          },
          {
            label: '执行状态',
            prop: 'state',
            showColumn: false,
            overHidden: true,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true
          },
          {
            label: '执行类',
            prop: 'jobClassName',
            type: 'select',
            hide: false,
            showColumn: true,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true,
            rules: [{
              required: true,
              message: '请选择一个任务执行类',
              trigger: 'blur'
            }],
            dicData: [],
            value: '',
            props: {
              label: 'value',
              value: 'key'
            }
          },
          {
            label: '正则表达式',
            prop: 'cronExpression',
            labelWidth: 100,
            type: 'input',
            hide: false,
            width: 150,
            span: 24,
            showWordLimit: true,
            maxlength: 100,
            showColumn: true,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true,
            rules: [{
              required: true,
              message: '请输入定时任务执行的正则表达式',
              trigger: 'blur'
            }],
            value: '0 0 1 * * ?'
          },
          {
            label: '开始执行时间',
            prop: 'prevFire',
            type: 'datetime',
            format: 'yyyy-MM-dd hh:mm:ss',
            width: 150,
            labelWidth: 100,
            hide: false,
            showColumn: true,
            overHidden: true,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true
          },
          {
            label: '下次执行时间',
            prop: 'nextFire',
            type: 'datetime',
            format: 'yyyy-MM-dd hh:mm:ss',
            width: 150,
            labelWidth: 100,
            span: 24,
            hide: false,
            showColumn: true,
            overHidden: true,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: true
          },
          {
            label: '执行参数',
            prop: 'jobData',
            type: 'textarea',
            hide: false,
            span: 24,
            showWordLimit: true,
            maxlength: 2000,
            showColumn: true,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true,
            placeholder: '输入该任务的相关运行参数,每个参数一行，格式为： 参数名=运行参数值，例如：name=小明',
            rules: [{
              required: false,
              message: '请输入执行参数',
              trigger: 'blur'
            }],
            value: '',
            // 对应输入的值转为数据库可存数据
            formatter (row, value, label, column) {
              let jobParams = ''
              Object.keys(row.jobData).forEach((key) => {
                const data = key + '=' + row.jobData[key]
                jobParams += data + '\n'
              })
              return jobParams
            }
          },
          {
            label: '失败是否自动恢复执行',
            prop: 'recovery',
            type: 'switch',
            hide: true,
            span: 12,
            labelWidth: 180,
            showColumn: false,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true,
            dicData: statusDic,
            value: false
          },
          {
            label: '创建后立即执行',
            prop: 'isPause',
            type: 'switch',
            hide: false,
            span: 12,
            labelWidth: 180,
            showColumn: false,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true,
            dicData: statusDic,
            value: false
          },
          {
            label: '任务描述',
            prop: 'description',
            type: 'textarea',
            span: 24,
            hide: true,
            showWordLimit: true,
            maxlength: 500,
            showColumn: false,
            overHidden: true,
            addDisplay: true,
            editDisplay: true,
            viewDisplay: true
          }
        ]
      },
      data: []
    }
  },
  computed: {
    ...mapGetters(['permissions', 'website']),
    ids () {
      const ids = []
      this.selectionList.forEach((e) => {
        ids.push(e.id)
      })
      return ids
    }
  },
  mounted () {
    this.fetchImplementJobData()
  },
  methods: {
    rowStyle ({ row, column, rowIndex }) {
      return {}
    },
    cellStyle ({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 2) {
        if (row.state === '失败' || row.state === '阻塞') {
          return {
            color: 'red',
            fontWeight: 'bold',
            fontSize: '20'
          }
        } else if (row.state === '等待' || row.state === '执行中') {
          return {
            color: 'rgba(255, 140, 0, 1)',
            fontWeight: 'bold',
            fontSize: '20'
          }
        } else if (row.state === '完成') {
          return {
            color: 'green',
            fontWeight: 'bold',
            fontSize: '20'
          }
        }
      }
      return {}
    },
    rowSave (row, loading, done) {
      loading()
      this.$store.dispatch(addJobAction, row).then((res) => {
        done()
        const resCode = res.code
        const message = res.message
        if (resCode === 0) {
          this.onLoad(this.page)
          this.$message({
            type: 'success',
            message: '保存操作成功!'
          })
        } else {
          this.$message({
            type: 'error',
            showClose: true,
            message: message || '保存数据失败,请稍后再试!'
          })
        }
      }).catch(() => {
        done()
        this.$message({
          type: 'error',
          showClose: true,
          message: '保存数据失败,请稍后再试!'
        })
      })
    },
    rowUpdate (row, index, loading, done) {
      loading()
      this.$store.dispatch(updateJobAction, row).then((res) => {
        done()
        const resCode = res.code
        const message = res.message
        if (resCode === 0) {
          this.onLoad(this.page)
          this.$message({
            type: 'success',
            message: '编辑操作成功!'
          })
        } else {
          this.$message({
            type: 'error',
            showClose: true,
            message: message || '编辑数据失败,请稍后再试!'
          })
        }
      }).catch(() => {
        done()
        this.$message({
          type: 'error',
          showClose: true,
          message: '编辑数据异常,请稍后再试!'
        })
      })
    },
    rowDel (row) {
      this.$confirm('确定将选择数据删除?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.loading = true
          const idParams = { jobName: row.jobName }
          return this.$store.dispatch(deleteJobAction, idParams)
        })
        .then((res) => {
          this.loading = false
          const resCode = res.code
          const message = res.message
          if (resCode === 0) {
            this.onLoad(this.page)
            this.$message({
              type: 'success',
              message: '删除操作成功!'
            })
          } else {
            this.loading = false
            this.$message({
              type: 'error',
              showClose: true,
              message: message || '删除数据失败,请稍后再试!'
            })
          }
        }).catch(() => {
          this.loading = false
        })
    },
    rowClick (row, event, column) {
      this.$refs.crud.rowView(row, column)
    },
    refresh ({ page, searchForm }) {
      this.onLoad(page)
    },
    beforeOpen (done, type) {
      if (['add'].includes(type)) {
        const index = this.$refs.crud.findColumnIndex('jobClassName')
        this.option.column[index].value = this.option.column[index].dicData[0].key
        // this.$set(this.form, 'jobClassName', this.option.column[index].dicData[0].key)
      } else if (['view', 'edit'].includes(type)) {
        let jobParams = ''
        Object.keys(this.form.jobData).forEach((key) => {
          const data = key + '=' + this.form.jobData[key]
          jobParams += data + '\n'
        })
        this.form.jobData = jobParams
      }
      done()
    },
    searchReset () {
      this.query = {}
      this.onLoad(this.page)
    },
    searchChange (params, done) {
      done()
      this.query = params
      this.page.currentPage = 1
      this.onLoad(this.page, params)
    },
    selectionChange (list) {
      this.selectionList = list
    },
    selectionClear () {
      this.selectionList = []
      this.$refs.crud.toggleSelection()
    },
    currentChange (currentPage) {
      this.page.currentPage = currentPage
    },
    sizeChange (pageSize) {
      this.page.pageSize = pageSize
    },
    onLoad (page, params = {}) {
      this.loading = true
      let queryData = {
        pageNo: page.currentPage,
        pageSize: page.pageSize
      }
      queryData = Object.assign(queryData, Object.assign(params, this.query))
      this.$store.dispatch(pageJobTasksAction, queryData).then((res) => {
        this.loading = false
        const resCode = res.code
        const message = res.message
        if (resCode === 0) {
          const data = res.data
          this.page.total = parseInt(data.total)
          this.data = data.records
          this.selectionClear()
          this.filterJobInfo(this.data)
        } else {
          this.$message({
            type: 'error',
            showClose: true,
            message: message || '查询数据失败,请稍后再试!'
          })
        }
      }).catch((err) => {
        console.log(err)
        this.$message({
          type: 'error',
          showClose: true,
          message: '查询数据异常,请稍后再试!'
        })
      })
    },
    fetchImplementJobData () {
      this.$store.dispatch(listImplementJobsAction).then((res) => {
        const resCode = res.code
        const message = res.message
        if (resCode === 0) {
          const index = this.$refs.crud.findColumnIndex('jobClassName')
          this.option.column[index].dicData = res.data
        } else {
          this.$message({
            type: 'error',
            message: message || '查询数据失败,请稍后再试!'
          })
        }
      }).catch((err) => {
        console.log(err)
        this.$message({
          type: 'error',
          message: '查询数据异常,请稍后再试!'
        })
      })
    },
    filterJobInfo (records) {
      this.job.total = 0
      this.job.pending = 0
      this.job.running = 0
      this.job.failed = 0
      this.job.total = records.length
      records.forEach((j) => {
        if (j.state === '失败') {
          this.job.failed += 1
        } else if (j.state === '阻塞' || j.state === '读取中' || j.state === '等待') {
          this.job.pending += 1
        } else if (j.state === '执行中') {
          this.job.running += 1
        }
      })
    },
    jobStatusText (row) {
      let status = ''
      if (row.state === '失败' || row.state === '等待') {
        status = '启动'
      } else if (row.state === '阻塞' || row.state === '读取中') {
        status = '停止'
      } else if (row.state === '执行中') {
        status = '暂停'
      } else {
        status = '启动'
      }
      return status
    },
    jobStatusHandler (row) {
      if (row.state === '失败' || row.state === '等待') {
        this.$store.dispatch(startJobAction, { jobName: row.jobName }).then((res) => {
          const resCode = res.code
          const message = res.message
          if (resCode === 0) {
            this.onLoad(this.page)
            this.$message({
              type: 'success',
              message: '启动任务操作完成!'
            })
          } else {
            this.loading = false
            this.$message({
              type: 'error',
              message: message || '启动任务失败,请稍后再试!'
            })
          }
        })
      } else if (row.state === '阻塞' || row.state === '读取中') {
        this.$store.dispatch(stopJobAction, { jobName: row.jobName }).then((res) => {
          const resCode = res.code
          const message = res.message
          if (resCode === 0) {
            this.onLoad(this.page)
            this.$message({
              type: 'success',
              message: '停止任务操作完成!'
            })
          } else {
            this.loading = false
            this.$message({
              type: 'error',
              message: message || '停止任务失败,请稍后再试!'
            })
          }
        })
      } else if (row.state === '执行中') {
        this.$store.dispatch(pauseJobAction, { jobName: row.jobName }).then((res) => {
          const resCode = res.code
          const message = res.message
          if (resCode === 0) {
            this.onLoad(this.page)
            this.$message({
              type: 'success',
              message: '暂停任务操作完成!'
            })
          } else {
            this.loading = false
            this.$message({
              type: 'error',
              message: message || '暂停任务失败,请稍后再试!'
            })
          }
        })
      } else {
        this.$store.dispatch(startJobAction, { jobName: row.jobName }).then((res) => {
          const resCode = res.code
          const message = res.message
          if (resCode === 0) {
            this.onLoad(this.page)
            this.$message({
              type: 'success',
              message: '启动任务操作完成!'
            })
          } else {
            this.loading = false
            this.$message({
              type: 'error',
              message: message || '启动任务失败,请稍后再试!'
            })
          }
        })
      }
    }
  },
  head () {
    return {
      title: '定时任务管理 | ' + this.website.name,
      meta: [
        { hid: 'description', name: 'description', content: '定时任务管理' }
      ]
    }
  }
}
</script>

<style lang="scss" scoped>
  .card {
    margin-bottom: 20px;
  }
  .head-info {
    text-align: center;
    padding: 0 32px;
    span{
      color: rgba(0,0,0,.45);
      display: inline-block;
      font-size: 14px;
      line-height: 22px;
      margin-bottom: 4px;
    }
    p {
      color: rgba(0,0,0,.85);
      font-size: 24px;
      line-height: 32px;
      margin: 0;
    }
  }
  .red {
    color: red !important;
  }
</style>
